home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 January: Mac OS SDK / Dev.CD Jan 99 SDK1.toast / Development Kits / ColorSync 2.5.1 SDK / Sample Code / DemoCMM / DemoCMM.c next >
Encoding:
C/C++ Source or Header  |  1998-09-09  |  24.0 KB  |  844 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        DemoCMM.c
  3.  
  4.     Contains:    Demo CMM Component for ColorSync 2.x
  5.                 
  6.                 This is a very simple CMM - so simple in fact that the only thing
  7.                 it uses from a profile is its colorspace.
  8.                 
  9.                 If the first (source) profile is RGB and the last (dest) profile
  10.                 is CMYK, then this CMM uses the simple "one minus" formula
  11.                 to convert from from RGB to CMYK.
  12.                 
  13.                 If the first (source) profile is CMYK and the last (dest) profile
  14.                 is RGB, then this CMM uses the inverse of the "one minus" formula
  15.                 to convert from from CMYK to RGB.
  16.  
  17.                 If the first and the last profile are RGB or if the first and the 
  18.                 last profile are CMYK, then this CMM leaves the colors unchanged.
  19.                 
  20.     Version:    ColorSync 2 or later
  21.  
  22.     Written by:    David Hayward
  23.  
  24.     Copyright:    © 1998 by Apple Computer, Inc., all rights reserved.
  25.  
  26.     Writers:
  27.         (DH)    David Hayward
  28.  
  29.     Change History (most recent first):
  30.  
  31.          <1>     7/16/98    DH        First checked in.
  32.  
  33. */
  34.  
  35. #include <ConditionalMacros.h>
  36. #include <MacTypes.h>
  37. #include <Memory.h>
  38. #include <Gestalt.h>
  39. #include <Components.h>
  40. #include <CMMComponent.h>
  41.  
  42.  
  43. #ifndef DEBUG
  44. #define DEBUG 0
  45. #endif
  46.  
  47.  
  48. // Component version
  49. #define     CMCodeVersion        1
  50. #define        CMMVersion            ((CMMInterfaceVersion << 16) | CMCodeVersion)
  51.  
  52.  
  53. // Component storage
  54. typedef struct
  55. {
  56.     ComponentInstance    ci;
  57.     OSType                srcSpace;
  58.     OSType                srcClass;
  59.     OSType                dstSpace;
  60.     OSType                dstClass;
  61. } CMMStorageRec, *CMMStoragePtr, **CMMStorageHdl;
  62.  
  63. // Match stuff
  64. typedef struct
  65. {
  66.     UInt32                height;
  67.     UInt32                width;
  68.     
  69.     OSType                srcSpace;
  70.     UInt8*                srcBuf[4];
  71.     UInt32                srcChanBits;
  72.     UInt32                srcRowBytes;
  73.     UInt32                srcColBytes;
  74.     
  75.     OSType                dstSpace;
  76.     UInt8*                dstBuf[4];
  77.     UInt32                dstChanBits;
  78.     UInt32                dstRowBytes;
  79.     UInt32                dstColBytes;
  80.     
  81. } CMMMatchRec, *CMMMatchPtr, **CMMMatchHdl;
  82.  
  83.  
  84. // Technique for Native PPC Component function calls from Tech Note "QT05-Component Mgr 3.0"
  85. #if TARGET_CPU_PPC
  86.     #define CCFWS(storage,params,name)    CallComponentFunctionWithStorage(storage, params, &name##RD)
  87.     #define CCF(params,name)             CallComponentFunction(params, &name##RD)
  88.     #define INSTANTIATE_RD(name)        RoutineDescriptor name##RD = BUILD_ROUTINE_DESCRIPTOR(upp##name##ProcInfo, name)
  89. #else
  90.     #define CCFWS(storage,params,name)    CallComponentFunctionWithStorage(storage, params, (ComponentFunctionUPP)name)
  91.     #define CCF(params,name)            CallComponentFunction(params, (ComponentFunctionUPP)name)
  92. #endif
  93.  
  94.  
  95. // proc infos
  96. enum {
  97.     uppDoComponentOpenProcInfo = kPascalStackBased
  98.          | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
  99.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(ComponentInstance))),
  100.     uppDoComponentCloseProcInfo = kPascalStackBased
  101.          | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
  102.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle)))
  103.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(ComponentInstance))),
  104.     uppDoComponentCanDoProcInfo = kPascalStackBased
  105.          | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
  106.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(short))),
  107.     uppDoComponentVersionProcInfo = kPascalStackBased
  108.          | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))),
  109.     uppDoComponentRegisterProcInfo = kPascalStackBased
  110.          | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))),
  111.     uppDoCMInitProcInfo = kPascalStackBased
  112.          | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
  113.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle)))
  114.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(CMProfileHandle)))
  115.          | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(CMProfileHandle))),
  116.     uppDoNCMInitProcInfo = kPascalStackBased
  117.          | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
  118.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle)))
  119.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(CMProfileRef)))
  120.          | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(CMProfileRef))),
  121.     uppDoCMConcatInitProcInfo = kPascalStackBased
  122.          | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
  123.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle)))
  124.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(CMConcatProfileSet*))),
  125.     uppDoCMMatchColorsProcInfo = kPascalStackBased
  126.          | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
  127.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle)))
  128.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(CMColor*)))
  129.          | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(unsigned long))),
  130.     uppDoCMCheckColorsProcInfo = kPascalStackBased
  131.          | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
  132.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle)))
  133.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(CMColor*)))
  134.          | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(unsigned long)))
  135.          | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(long*))),
  136.     uppDoCMMatchBitmapProcInfo = kPascalStackBased
  137.          | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
  138.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle)))
  139.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(CMBitmap*)))
  140.          | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(CMBitmapCallBackUPP)))
  141.          | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(void*)))
  142.          | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(CMBitmap*))),
  143.     uppDoCMCheckBitmapProcInfo = kPascalStackBased
  144.          | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
  145.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle)))
  146.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(CMBitmap*)))
  147.          | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(CMBitmapCallBackUPP)))
  148.          | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(void*)))
  149.          | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(CMBitmap*)))
  150. };
  151.  
  152.  
  153. // function prototypes
  154. pascal ComponentResult main                            (ComponentParameters *params, Handle storage);
  155. static pascal ComponentResult DoComponentOpen        (ComponentInstance self);
  156. static pascal ComponentResult DoComponentClose        (CMMStorageHdl storage, ComponentInstance self);
  157. static pascal ComponentResult DoComponentCanDo        (short selector);
  158. static pascal ComponentResult DoComponentVersion    (void);
  159. static pascal ComponentResult DoComponentRegister    (void);
  160. static pascal ComponentResult DoCMInit                (CMMStorageHdl storage, CMProfileHandle srcProfile, CMProfileHandle dstProfile);
  161. static pascal ComponentResult DoNCMInit                (CMMStorageHdl storage, CMProfileRef srcProfile, CMProfileRef dstProfile);
  162. static pascal ComponentResult DoCMConcatInit        (CMMStorageHdl storage, CMConcatProfileSet* profileSet);
  163. static pascal ComponentResult DoCMMatchColors        (CMMStorageHdl storage, CMColor *colorBuf, unsigned long count);
  164. static pascal ComponentResult DoCMCheckColors        (CMMStorageHdl storage, CMColor *colorBuf, unsigned long count, long *gamutResult);
  165. static pascal ComponentResult DoCMMatchBitmap        (CMMStorageHdl storage, const CMBitmap * srcMap, CMBitmapCallBackUPP progressProc, void* refCon, CMBitmap* dstMap);
  166. static pascal ComponentResult DoCMCheckBitmap        (CMMStorageHdl storage, const CMBitmap * srcMap, CMBitmapCallBackUPP progressProc, void* refCon, CMBitmap* chkMap);
  167. static ComponentResult CheckStorage                    (CMMStorageHdl storage);
  168. static void            SimpleMatchAll                (CMMMatchPtr pMatchInfo);
  169. static void            SimpleMatchOne                (CMMMatchPtr pMatchInfo, UInt16* chan);
  170.  
  171.  
  172. // RoutineDescriptors
  173. #if TARGET_CPU_PPC
  174.     // RoutineDescriptors for Component functions
  175.     INSTANTIATE_RD(DoComponentOpen);
  176.     INSTANTIATE_RD(DoComponentClose);
  177.     INSTANTIATE_RD(DoComponentCanDo);
  178.     INSTANTIATE_RD(DoComponentVersion);
  179.     INSTANTIATE_RD(DoComponentRegister);
  180.     INSTANTIATE_RD(DoCMInit);
  181.     INSTANTIATE_RD(DoNCMInit);
  182.     INSTANTIATE_RD(DoCMConcatInit);
  183.     INSTANTIATE_RD(DoCMMatchColors);
  184.     INSTANTIATE_RD(DoCMCheckColors);
  185.     INSTANTIATE_RD(DoCMMatchBitmap);
  186.     INSTANTIATE_RD(DoCMCheckBitmap);
  187.  
  188.     // PowerPC main Component entry point
  189.     RoutineDescriptor mainRD = BUILD_ROUTINE_DESCRIPTOR(uppComponentRoutineProcInfo, main);
  190. //    ProcInfoType __procinfo = uppComponentRoutineProcInfo;
  191. #endif
  192.  
  193.  
  194. #if TARGET_CPU_68K
  195. #pragma code68020 off                        // this functions must run on all Macs
  196. #endif
  197.  
  198. /* ______________________________________________________________________
  199.  
  200.     ComponentResult
  201.  
  202.     Abstract:
  203.         main entry point to CMM Component
  204.  
  205.     Params:
  206.         params        (in)    Parameters in form used by Component Manager
  207.         storage        (in)    Handle to memory to be used by CMM
  208.         
  209.     Return:
  210.         noErr        If successful
  211.                     Otherwise System or ColorSync result code
  212.  
  213.    _____________________________________________________________________ */
  214.  
  215.  
  216. pascal ComponentResult
  217. main (ComponentParameters *params, Handle storage)
  218. {
  219.     ComponentResult        result = noErr;        /* Init for error handling */
  220.     short                message;        
  221.  
  222.     message = (*params).what;
  223.  
  224.     /* Selectors < 0 for Component Manager functions */ 
  225.     if (message < 0)
  226.     {
  227.         switch (message)
  228.         {
  229.             case kComponentOpenSelect :
  230.             result = CCF(params, DoComponentOpen);
  231.             break;
  232.             
  233.             case kComponentCloseSelect :
  234.             result = CCFWS(storage, params, DoComponentClose);
  235.             break;
  236.             
  237.             case kComponentCanDoSelect :
  238.             result = CCF(params, DoComponentCanDo);
  239.             break;
  240.             
  241.             case kComponentVersionSelect :
  242.             result = CCF(params, DoComponentVersion);
  243.             break;
  244.             
  245.             case kComponentRegisterSelect :
  246.             result = CCF(params, DoComponentRegister);
  247.             break;
  248.             
  249.             default :
  250.             result = noErr;
  251.             break;
  252.         }
  253.     }
  254.     else /* Selectors >= 0 for CMM functions */ 
  255.     {
  256.         switch (message)
  257.         {
  258.              case kCMMInit :
  259.             result = CCFWS(storage, params, DoCMInit);
  260.             break;
  261.             
  262.              case kNCMMInit :
  263.             result = CCFWS(storage, params, DoNCMInit);
  264.             break;
  265.             
  266.              case kCMMConcatInit :
  267.             result = CCFWS(storage, params, DoCMConcatInit);
  268.             break;
  269.             
  270.              case kCMMMatchColors :
  271.             result = CCFWS(storage, params, DoCMMatchColors);
  272.             break;
  273.             
  274.              case kCMMCheckColors :
  275.             result = CCFWS(storage, params, DoCMCheckColors);
  276.             break;
  277.             
  278.              case kCMMMatchBitmap :
  279.             result = CCFWS(storage, params, DoCMMatchBitmap);
  280.             break;
  281.             
  282.              case kCMMCheckBitmap :
  283.             result = CCFWS(storage, params, DoCMCheckBitmap);
  284.             break;
  285.             
  286.             default :
  287.             result = unimpErr;
  288.             break;
  289.         }
  290.     }
  291.     return result ;
  292. }
  293.  
  294.  
  295. static pascal ComponentResult
  296. DoComponentOpen (ComponentInstance self)
  297. {
  298.     ComponentResult        result = noErr;        /* Init for error handling */
  299.     CMMStorageHdl        h;
  300.     
  301.     h = (CMMStorageHdl) NewHandleClear(sizeof(CMMStorageRec));
  302.     if (h == nil)
  303.         result = MemError();
  304.     
  305.     if (result == noErr)
  306.     {
  307.         (**h).ci = self;
  308.         SetComponentInstanceStorage(self, (Handle) h);
  309.     }
  310.     
  311.     return result ;
  312. }
  313.  
  314.  
  315. static pascal
  316. ComponentResult
  317. DoComponentClose(CMMStorageHdl storage, ComponentInstance self)
  318. {
  319.     ComponentResult        result = noErr;        /* Init for error handling */
  320.     
  321.     if (storage != nil)
  322.         DisposeHandle((Handle)storage);
  323.     
  324.     return result ;
  325. }
  326.  
  327. static pascal
  328. ComponentResult
  329. DoComponentRegister(void)
  330. {
  331.     ComponentResult        result = noErr;        /* Init for error handling */
  332.     long                gestaltCPU;
  333.     long                gestaltSys;
  334.     long                gestaltQD;
  335.     
  336.     // Default -- don't register
  337.     result    = 1;
  338.     
  339.     // We require 68020 processor and 32-Bit Color QD 1.2
  340.     // gestalt68020 is returned for gestaltProcessorType on PowerPC
  341.     if ((Gestalt(gestaltProcessorType, &gestaltCPU) == noErr)    && (gestaltCPU >= gestalt68020)        &&
  342.         (Gestalt(gestaltSystemVersion, &gestaltSys) == noErr)    && (gestaltSys >= 0x0700)            &&
  343.         (Gestalt(gestaltQuickdrawVersion, &gestaltQD) == noErr)    && (gestaltQD >= gestalt32BitQD12))
  344.     {
  345.         // OK to register
  346.         result = 0;
  347.     }
  348.     
  349.     return result ;
  350. }
  351.  
  352.  
  353. #if TARGET_CPU_68K
  354. #pragma code68020 reset
  355. #endif
  356.  
  357.  
  358. static pascal
  359. ComponentResult
  360. DoComponentCanDo(short selector)
  361. {
  362.     ComponentResult        result = noErr;        /* Init for error handling */
  363.  
  364.     switch (selector)
  365.     {
  366.         /* Component Manager functions */
  367.         case kComponentOpenSelect:                // -1
  368.         case kComponentCloseSelect:                // -2
  369.         case kComponentCanDoSelect:                // -3
  370.         case kComponentVersionSelect:            // -4
  371.         case kComponentRegisterSelect:            // -5
  372.         result = true;
  373.         break;
  374.         
  375.         /* Supported CMM functions */
  376.         case kCMMInit:                            // 0
  377.         case kNCMMInit:                            // 6
  378.         case kCMMMatchColors:                    // 1
  379.         case kCMMCheckColors:                    // 2
  380.         case kCMMConcatInit:                    // 7
  381.         case kCMMMatchBitmap:                    // 9
  382.         case kCMMCheckBitmap:                    // 10
  383.         result = true;
  384.         break;
  385.  
  386.         /* Unsupported CMM functions */
  387.         case kCMMMatchPixMap:                    // 3
  388.         case kCMMCheckPixMap:                    // 4
  389.         case kCMMConcatenateProfiles:            // 5
  390.         case kCMMValidateProfile:                // 8
  391.         case kCMMGetPS2ColorSpace:                // 11
  392.         case kCMMGetPS2ColorRenderingIntent:    // 12
  393.         case kCMMGetPS2ColorRendering:            // 13
  394.         case kCMMFlattenProfile:                // 14
  395.         case kCMMUnflattenProfile:                // 15
  396.         case kCMMNewLinkProfile:                // 16
  397.         case kCMMGetPS2ColorRenderingVMSize:    // 17
  398.         result = false;
  399.         break; 
  400.             
  401.         default:
  402.         result = false;
  403.         break; 
  404.     }
  405.  
  406.     return result ;
  407. }
  408.  
  409.  
  410. static pascal
  411. ComponentResult
  412. DoComponentVersion(void)
  413. {
  414.     return CMMVersion;
  415. }
  416.  
  417.  
  418. static pascal
  419. ComponentResult
  420. DoCMInit(CMMStorageHdl storage, CMProfileHandle srcProfile, CMProfileHandle dstProfile)
  421. {    
  422.     // Check params
  423.     if ((srcProfile == nil) || (dstProfile == nil))
  424.         return paramErr;
  425.     
  426.     (**storage).srcSpace = (**srcProfile).header.dataType;
  427.     (**storage).srcClass = (**srcProfile).header.deviceType;
  428.     
  429.     (**storage).dstSpace = (**dstProfile).header.dataType;
  430.     (**storage).dstClass = (**dstProfile).header.deviceType;
  431.  
  432.     return CheckStorage(storage);
  433. }
  434.                                 
  435.  
  436. typedef struct CMConcatProfileSet2 {
  437.     unsigned short         keyIndex;        /* Zero-based */
  438.     unsigned short         count;            /* Min 1, Max 2 */
  439.     CMProfileRef         profileSet[2];    /* Fixed. Source and Dest */
  440. } CMConcatProfileSet2;
  441.  
  442. static pascal
  443. ComponentResult
  444. DoNCMInit (CMMStorageHdl storage, CMProfileRef srcProfile, CMProfileRef dstProfile)
  445. {
  446.     CMConcatProfileSet2        set;
  447.     
  448.     set.keyIndex = 0;
  449.     set.count = 2;
  450.     set.profileSet[0] = srcProfile;
  451.     set.profileSet[1] = dstProfile;
  452.         
  453.     return DoCMConcatInit(storage, (CMConcatProfileSet*)&set);
  454. }
  455.  
  456.  
  457. static pascal
  458. ComponentResult
  459. DoCMConcatInit (CMMStorageHdl storage, CMConcatProfileSet* profileSet)
  460. {
  461.     ComponentResult            result = noErr;        /* Init for error handling */
  462.     CMAppleProfileHeader    srcHdr;
  463.     CMAppleProfileHeader    dstHdr;
  464.     CMProfileRef            srcProfile;
  465.     CMProfileRef            dstProfile;
  466.     
  467.     // Check params
  468.     if (profileSet==nil)
  469.         return paramErr;
  470.     
  471.     srcProfile = profileSet->profileSet[0];
  472.     dstProfile = profileSet->profileSet[profileSet->count-1];
  473.     if ((srcProfile == nil) || (dstProfile == nil))
  474.         return paramErr;
  475.     
  476.     if (result == noErr)
  477.         result = CMGetProfileHeader(srcProfile, &srcHdr);
  478.     
  479.     if (result == noErr)
  480.         result = CMGetProfileHeader(dstProfile, &dstHdr);
  481.     
  482.     if (result == noErr)
  483.     {
  484.         (**storage).srcSpace = srcHdr.cm2.dataColorSpace;
  485.         (**storage).srcClass = srcHdr.cm2.profileClass;
  486.         
  487.         (**storage).dstSpace = dstHdr.cm2.dataColorSpace;
  488.         (**storage).dstClass = dstHdr.cm2.profileClass;
  489.         
  490.         result = CheckStorage(storage);
  491.     }
  492.         
  493.     return result ;
  494. }
  495.  
  496.  
  497.  
  498. static pascal
  499. ComponentResult
  500. DoCMMatchColors (CMMStorageHdl storage, CMColor *colorBuf, unsigned long count)
  501. {
  502.     CMMMatchRec            matchInfo;
  503.     
  504.     matchInfo.height        = count;
  505.     matchInfo.width            = 1;
  506.     matchInfo.srcSpace        = (**storage).srcSpace;
  507.     matchInfo.srcBuf[0]        = ((UInt8*)colorBuf) + 0;
  508.     matchInfo.srcBuf[1]        = ((UInt8*)colorBuf) + 2;
  509.     matchInfo.srcBuf[2]        = ((UInt8*)colorBuf) + 4;
  510.     matchInfo.srcBuf[3]        = ((UInt8*)colorBuf) + 6;
  511.     matchInfo.srcChanBits    = 16;
  512.     matchInfo.srcRowBytes    = sizeof(CMColor);
  513.     matchInfo.srcColBytes    = sizeof(CMColor);
  514.     matchInfo.dstSpace        = (**storage).dstSpace;
  515.     matchInfo.dstBuf[0]        = ((UInt8*)colorBuf) + 0;
  516.     matchInfo.dstBuf[1]        = ((UInt8*)colorBuf) + 2;
  517.     matchInfo.dstBuf[2]        = ((UInt8*)colorBuf) + 4;
  518.     matchInfo.dstBuf[3]        = ((UInt8*)colorBuf) + 6;
  519.     matchInfo.dstChanBits    = 16;
  520.     matchInfo.dstRowBytes    = sizeof(CMColor);
  521.     matchInfo.dstColBytes    = sizeof(CMColor);
  522.     
  523.     SimpleMatchAll(&matchInfo);
  524.     
  525.     return noErr;
  526. }
  527.                                 
  528.  
  529. static pascal
  530. ComponentResult
  531. DoCMCheckColors (CMMStorageHdl storage,  CMColor *colorBuf, unsigned long count, long* gamutResult)
  532. {
  533. #pragma unused (storage, colorBuf)
  534.     
  535.     unsigned long        longCount;
  536.     
  537.     /* Everything is in gamut. This is just sample code. */
  538.     
  539.     longCount = (count + 31) / 32;
  540.     
  541.     while (longCount--)
  542.         *gamutResult++ = 0xFFFFFFFF;
  543.     
  544.     return noErr;
  545. }
  546.  
  547.  
  548. static pascal
  549. ComponentResult
  550. DoCMMatchBitmap (CMMStorageHdl storage,  const CMBitmap * srcMap,
  551.                  CMBitmapCallBackUPP progressProc, void * refCon,
  552.                  CMBitmap* dstMap)
  553. {
  554. #pragma unused (progressProc, refCon)
  555.     
  556.     CMMMatchRec            matchInfo;
  557.     
  558.     // Check params
  559.     if (srcMap==nil || dstMap==nil)
  560.         return paramErr;
  561.     
  562.     matchInfo.height        = srcMap->height;
  563.     matchInfo.width            = srcMap->width;
  564.     matchInfo.srcRowBytes    = srcMap->rowBytes;
  565.     matchInfo.dstRowBytes    = dstMap->rowBytes;
  566.     
  567.     switch (srcMap->space)
  568.     {
  569.         case cmRGB24Space:
  570.         matchInfo.srcSpace        = cmRGBData;
  571.         matchInfo.srcBuf[0]        = (UInt8*)srcMap->image + 0;
  572.         matchInfo.srcBuf[1]        = (UInt8*)srcMap->image + 1;
  573.         matchInfo.srcBuf[2]        = (UInt8*)srcMap->image + 2;
  574.         matchInfo.srcBuf[3]        = nil;
  575.         matchInfo.srcChanBits    = 8;
  576.         matchInfo.srcColBytes    = 3;
  577.         break;
  578.         
  579.         case cmRGB32Space:
  580.         matchInfo.srcSpace        = cmRGBData;
  581.         matchInfo.srcBuf[0]        = (UInt8*)srcMap->image + 1;
  582.         matchInfo.srcBuf[1]        = (UInt8*)srcMap->image + 2;
  583.         matchInfo.srcBuf[2]        = (UInt8*)srcMap->image + 3;
  584.         matchInfo.srcBuf[3]        = nil;
  585.         matchInfo.srcChanBits    = 8;
  586.         matchInfo.srcColBytes    = 4;
  587.         break;
  588.         
  589.         case cmRGB48Space:
  590.         matchInfo.srcSpace        = cmRGBData;
  591.         matchInfo.srcBuf[0]        = (UInt8*)srcMap->image + 0;
  592.         matchInfo.srcBuf[1]        = (UInt8*)srcMap->image + 2;
  593.         matchInfo.srcBuf[2]        = (UInt8*)srcMap->image + 4;
  594.         matchInfo.srcBuf[3]        = nil;
  595.         matchInfo.srcChanBits    = 16;
  596.         matchInfo.srcColBytes    = 6;
  597.         break;
  598.         
  599.         case cmCMYK32Space:
  600.         matchInfo.srcSpace        = cmCMYKData;
  601.         matchInfo.srcBuf[0]        = (UInt8*)srcMap->image + 0;
  602.         matchInfo.srcBuf[1]        = (UInt8*)srcMap->image + 1;
  603.         matchInfo.srcBuf[2]        = (UInt8*)srcMap->image + 2;
  604.         matchInfo.srcBuf[3]        = (UInt8*)srcMap->image + 3;
  605.         matchInfo.srcChanBits    = 8;
  606.         matchInfo.srcColBytes    = 4;
  607.         break;
  608.         
  609.         case cmCMYK64Space:
  610.         matchInfo.srcSpace        = cmCMYKData;
  611.         matchInfo.srcBuf[0]        = (UInt8*)srcMap->image + 0;
  612.         matchInfo.srcBuf[1]        = (UInt8*)srcMap->image + 2;
  613.         matchInfo.srcBuf[2]        = (UInt8*)srcMap->image + 4;
  614.         matchInfo.srcBuf[3]        = (UInt8*)srcMap->image + 6;
  615.         matchInfo.srcChanBits    = 16;
  616.         matchInfo.srcColBytes    = 8;
  617.         break;
  618.         
  619.         default:
  620.         return cmInvalidSrcMap;
  621.         break;
  622.     }
  623.     
  624.     
  625.     switch (dstMap->space)
  626.     {
  627.         case cmRGB24Space:
  628.         matchInfo.dstSpace        = cmRGBData;
  629.         matchInfo.dstBuf[0]        = (UInt8*)dstMap->image + 0;
  630.         matchInfo.dstBuf[1]        = (UInt8*)dstMap->image + 1;
  631.         matchInfo.dstBuf[2]        = (UInt8*)dstMap->image + 2;
  632.         matchInfo.dstBuf[3]        = nil;
  633.         matchInfo.dstChanBits    = 8;
  634.         matchInfo.dstColBytes    = 3;
  635.         break;
  636.         
  637.         case cmRGB32Space:
  638.         matchInfo.dstSpace        = cmRGBData;
  639.         matchInfo.dstBuf[0]        = (UInt8*)dstMap->image + 1;
  640.         matchInfo.dstBuf[1]        = (UInt8*)dstMap->image + 2;
  641.         matchInfo.dstBuf[2]        = (UInt8*)dstMap->image + 3;
  642.         matchInfo.dstBuf[3]        = nil;
  643.         matchInfo.dstChanBits    = 8;
  644.         matchInfo.dstColBytes    = 4;
  645.         break;
  646.         
  647.         case cmRGB48Space:
  648.         matchInfo.dstSpace        = cmRGBData;
  649.         matchInfo.dstBuf[0]        = (UInt8*)dstMap->image + 0;
  650.         matchInfo.dstBuf[1]        = (UInt8*)dstMap->image + 2;
  651.         matchInfo.dstBuf[2]        = (UInt8*)dstMap->image + 4;
  652.         matchInfo.dstBuf[3]        = nil;
  653.         matchInfo.dstChanBits    = 16;
  654.         matchInfo.dstColBytes    = 6;
  655.         break;
  656.         
  657.         case cmCMYK32Space:
  658.         matchInfo.dstSpace        = cmCMYKData;
  659.         matchInfo.dstBuf[0]        = (UInt8*)dstMap->image + 0;
  660.         matchInfo.dstBuf[1]        = (UInt8*)dstMap->image + 1;
  661.         matchInfo.dstBuf[2]        = (UInt8*)dstMap->image + 2;
  662.         matchInfo.dstBuf[3]        = (UInt8*)dstMap->image + 3;
  663.         matchInfo.dstChanBits    = 8;
  664.         matchInfo.dstColBytes    = 4;
  665.         break;
  666.         
  667.         case cmCMYK64Space:
  668.         matchInfo.dstSpace        = cmCMYKData;
  669.         matchInfo.dstBuf[0]        = (UInt8*)dstMap->image + 0;
  670.         matchInfo.dstBuf[1]        = (UInt8*)dstMap->image + 2;
  671.         matchInfo.dstBuf[2]        = (UInt8*)dstMap->image + 4;
  672.         matchInfo.dstBuf[3]        = (UInt8*)dstMap->image + 6;
  673.         matchInfo.dstChanBits    = 16;
  674.         matchInfo.dstColBytes    = 8;
  675.         break;
  676.         
  677.         default:
  678.         return cmInvalidSrcMap;
  679.         break;
  680.     }
  681.     
  682.     
  683.     if ((**storage).srcSpace != matchInfo.srcSpace)
  684.         return cmInvalidSrcMap;
  685.     
  686.     
  687.     if ((**storage).dstSpace != matchInfo.dstSpace)
  688.         return cmInvalidDstMap;
  689.     
  690.     SimpleMatchAll(&matchInfo);
  691.     
  692.     return noErr;
  693. }
  694.  
  695.  
  696. static pascal
  697. ComponentResult
  698. DoCMCheckBitmap (CMMStorageHdl storage,  const CMBitmap * srcMap,
  699.                  CMBitmapCallBackUPP progressProc, void * refCon,
  700.                  CMBitmap* chkMap)
  701. {
  702. #pragma unused (storage, srcMap, progressProc, refCon, chkMap)
  703.     return paramErr;
  704. }
  705.  
  706.  
  707. static
  708. ComponentResult
  709. CheckStorage (CMMStorageHdl storage)
  710. {
  711.     if (((**storage).srcSpace != cmRGBData) &&
  712.         ((**storage).srcSpace != cmCMYKData))
  713.         return cmInvalidProfile;
  714.     
  715.     if (((**storage).dstSpace != cmRGBData) &&
  716.         ((**storage).dstSpace != cmCMYKData))
  717.         return cmInvalidProfile;
  718.     
  719.     return noErr;
  720. }
  721.  
  722.  
  723. static
  724. void
  725. DebugColor4( UInt16* color)
  726. {
  727.     Str255            s = "\p 0xXXXX, 0xXXXX, 0xXXXX, 0xXXXX ";
  728.     UInt8*            c = &(s[4]);
  729.     int                i;
  730.     int                v;
  731.     
  732.     for (i=0; i<4; i++)
  733.     {
  734.         v = (((*color)>>12) & 0x000F);    *c++ = (v<10) ? (v+'0') : (v+'A'-10);
  735.         v = (((*color)>>8) & 0x000F);    *c++ = (v<10) ? (v+'0') : (v+'A'-10);
  736.         v = (((*color)>>4) & 0x000F);    *c++ = (v<10) ? (v+'0') : (v+'A'-10);
  737.         v = (((*color)) & 0x000F);        *c++ = (v<10) ? (v+'0') : (v+'A'-10);
  738.         c += 4;
  739.         color++;
  740.     }
  741.     DebugStr(s);
  742. }
  743.  
  744.  
  745. //
  746. // Simple conversion of a bunch or colors. This is just sample code.
  747. //
  748. static
  749. void
  750. SimpleMatchAll (CMMMatchPtr pMatchInfo)
  751. {
  752.     UInt32                r,c;
  753.     UInt16                chan[4];
  754.     UInt8**                sBuf;
  755.     UInt8**                dBuf;
  756.     
  757.     sBuf = pMatchInfo->srcBuf;
  758.     dBuf = pMatchInfo->dstBuf;
  759.     
  760.     for (r=0; r < pMatchInfo->height; r++)
  761.     {
  762.         for (c=0; c < pMatchInfo->width; c++)
  763.         {
  764.             // read color in from source buffer
  765.             if (pMatchInfo->srcChanBits==16)
  766.             {
  767.                 if (sBuf[0]) chan[0] = *(UInt16*)(sBuf[0] + (r * pMatchInfo->srcRowBytes) + (c * pMatchInfo->srcColBytes));
  768.                 if (sBuf[1]) chan[1] = *(UInt16*)(sBuf[1] + (r * pMatchInfo->srcRowBytes) + (c * pMatchInfo->srcColBytes));
  769.                 if (sBuf[2]) chan[2] = *(UInt16*)(sBuf[2] + (r * pMatchInfo->srcRowBytes) + (c * pMatchInfo->srcColBytes));
  770.                 if (sBuf[3]) chan[3] = *(UInt16*)(sBuf[3] + (r * pMatchInfo->srcRowBytes) + (c * pMatchInfo->srcColBytes));
  771.             }
  772.             else
  773.             {
  774.                 if (sBuf[0]) chan[0] = *(UInt8*)(sBuf[0] + (r * pMatchInfo->srcRowBytes) + (c * pMatchInfo->srcColBytes));
  775.                 if (sBuf[1]) chan[1] = *(UInt8*)(sBuf[1] + (r * pMatchInfo->srcRowBytes) + (c * pMatchInfo->srcColBytes));
  776.                 if (sBuf[2]) chan[2] = *(UInt8*)(sBuf[2] + (r * pMatchInfo->srcRowBytes) + (c * pMatchInfo->srcColBytes));
  777.                 if (sBuf[3]) chan[3] = *(UInt8*)(sBuf[3] + (r * pMatchInfo->srcRowBytes) + (c * pMatchInfo->srcColBytes));
  778.                 chan[0] = (chan[0] << 8) | chan[0];
  779.                 chan[1] = (chan[1] << 8) | chan[1];
  780.                 chan[2] = (chan[2] << 8) | chan[2];
  781.                 chan[3] = (chan[3] << 8) | chan[3];
  782.             }
  783.             
  784.             // DebugColor4(chan);
  785.             
  786.             // Match the color
  787.             SimpleMatchOne(pMatchInfo, chan);
  788.             
  789.             // DebugColor4(chan);
  790.             
  791.             // Write color to destination buffer
  792.             if (pMatchInfo->dstChanBits==16)
  793.             {
  794.                 if (dBuf[0]) *(UInt16*)(dBuf[0] + (r * pMatchInfo->dstRowBytes) + (c * pMatchInfo->dstColBytes)) = chan[0];
  795.                 if (dBuf[1]) *(UInt16*)(dBuf[1] + (r * pMatchInfo->dstRowBytes) + (c * pMatchInfo->dstColBytes)) = chan[1];
  796.                 if (dBuf[2]) *(UInt16*)(dBuf[2] + (r * pMatchInfo->dstRowBytes) + (c * pMatchInfo->dstColBytes)) = chan[2];
  797.                 if (dBuf[3]) *(UInt16*)(dBuf[3] + (r * pMatchInfo->dstRowBytes) + (c * pMatchInfo->dstColBytes)) = chan[3];
  798.             }
  799.             else
  800.             {
  801.                 if (dBuf[0]) *(UInt8*)(dBuf[0] + (r * pMatchInfo->dstRowBytes) + (c * pMatchInfo->dstColBytes)) = chan[0] >> 8;
  802.                 if (dBuf[1]) *(UInt8*)(dBuf[1] + (r * pMatchInfo->dstRowBytes) + (c * pMatchInfo->dstColBytes)) = chan[1] >> 8;
  803.                 if (dBuf[2]) *(UInt8*)(dBuf[2] + (r * pMatchInfo->dstRowBytes) + (c * pMatchInfo->dstColBytes)) = chan[2] >> 8;
  804.                 if (dBuf[3]) *(UInt8*)(dBuf[3] + (r * pMatchInfo->dstRowBytes) + (c * pMatchInfo->dstColBytes)) = chan[3] >> 8;
  805.             }
  806.         }
  807.     }
  808. }
  809.  
  810.  
  811. //
  812. // Simple conversion of one color with 16 bits-per-channel 
  813. //
  814. static
  815. void
  816. SimpleMatchOne (CMMMatchPtr pMatchInfo, UInt16* chan)
  817. {
  818.     if (pMatchInfo->srcSpace != pMatchInfo->dstSpace)
  819.     {
  820.         if ((pMatchInfo->srcSpace == cmRGBData) && (pMatchInfo->dstSpace == cmCMYKData))
  821.         {
  822.             chan[0] = 0xFFFF - chan[0];
  823.             chan[1] = 0xFFFF - chan[1];
  824.             chan[2] = 0xFFFF - chan[2];
  825.             chan[3] = (chan[0] < chan[1]) ?
  826.                         ( (chan[0] < chan[2]) ? (chan[0]) : (chan[2]) ) :
  827.                         ( (chan[1] < chan[2]) ? (chan[1]) : (chan[2]) );
  828.             chan[0] -= chan[3];
  829.             chan[1] -= chan[3];
  830.             chan[2] -= chan[3];
  831.         }
  832.     
  833.         if ((pMatchInfo->srcSpace == cmCMYKData) && (pMatchInfo->dstSpace == cmRGBData))
  834.         {
  835.             chan[0] = 0xFFFF - chan[0];
  836.             chan[1] = 0xFFFF - chan[1];
  837.             chan[2] = 0xFFFF - chan[2];
  838.             chan[0] = (chan[0] > chan[3]) ? (chan[0] - chan[3]) : 0;
  839.             chan[1] = (chan[1] > chan[3]) ? (chan[1] - chan[3]) : 0;
  840.             chan[2] = (chan[2] > chan[3]) ? (chan[2] - chan[3]) : 0;
  841.             chan[3] = 0;
  842.         }
  843.     }
  844. }